package Batch::Simple;

use Modern::Perl;

use Moose;
use IO::File;
use File::Temp ();
use Data::Dumper;
use Batch::Simple::Result;
use autodie qw{ open close };

our $VERSION = '0.01';

# -----------------------------
# Comentario creado en el TRUNK
# -----------------------------
# Comentario creado en el BRANCH1
# -----------------------------

# Preloaded methods go here.


has 'command' =>
(
	is => 'rw',
	isa => 'Str',
	required => 1,
);

has 'options' =>
(
	is => 'rw',
	isa => 'ArrayRef[Str]',
	required => 0,
	default => sub { [] },
);

has 'input' =>
(
	is => 'rw',
	#isa => 'IO::File',
	isa => 'Any',
	predicate => 'has_input', # dice si esta o no inicializado el atributo
	clearer => 'clear_input',
	required => 0,
	#default => sub { IO::File->new_from_fd(fileno(STDIN),"r") },
);

around BUILDARGS => sub 
{
	my $orig = shift;
	my $class = shift;	
	if ( @_ == 1 && ! ref $_[0] ) 
	{
		return $class->$orig(command => $_[0]);
	}
	else 
	{
		return $class->$orig(@_);
	}
};


sub run
{
	my $self = shift;

	# Salvamos STDERR
	my $SAVESTDERR = IO::File->new_from_fd(fileno(STDERR),"w");

	# Fichero temporal para redirigir STDERR
	my $NEWSTDERR = File::Temp->new(); 
	my $new_stderr_filename = $NEWSTDERR->filename();

	# Redirigimos STDERR al nuevo manejador
	STDERR->fdopen(fileno($NEWSTDERR), "w");

	my $SAVESTDIN;
	my $entrada = '';
	if ($self->has_input)
	{
		my $input = $self->input;
		if (ref $input eq 'SCALAR')
		{
			$entrada = $$input;
		}
		else
		{
			$SAVESTDIN = IO::File->new_from_fd(fileno(STDIN),"r");	
			die "Error! no se pudo abrir $input. \n" unless -r $input;
			open STDIN, '<', $input;
		}
	}
	
	# Ejecutamos el comando
	my ($command, @options) = ($self->command, @{$self->options});
	my $stdout = qx($command @options $entrada);
	my $status = $?;
	
	# Recuperamos STDERR
    STDERR->fdopen(fileno($SAVESTDERR), "w");
    
    # Cerramos el fichero para asegurarnos que nada se quede en los buffers
	$NEWSTDERR->close();
	
	if ($self->has_input and $entrada eq '')
	{
		STDIN->fdopen(fileno($SAVESTDIN), "r");
		$SAVESTDIN->close();		
	}
	
	# Leemos la salida del comando por STDERR
	my $STDERR_FILE = IO::File->new();
	$STDERR_FILE->open($new_stderr_filename, "r");
	local $/;
	my $stderr = <$STDERR_FILE>;
	$STDERR_FILE->close();
	
	# Devolvemos un objeto Result
	return Batch::Simple::Result->new(stdout => $stdout, stderr => $stderr, status => $status);
}

1;

__END__

=head1 NAME

Batch::Simple - Módulo para la ejecución de un programa controlando las salidas

=head1 SYNOPSIS

 	use Batch::Simple;
  
 	my $batch = Batch::Simple->new(command => $ls, options => [ $etc_passwd ]);
	my $result = $batch->run();

	ok($result->stdout() eq "/etc/passwd\n", 'Testing ok stdout');

=head1 DESCRIPTION

Con este módulo, tendremos una extensión de la funcionalidad de qx, pudiendo obtener tanto
la salida por STDOUT como por STDERR, así como el estatus del programa al terminar.

Además, podremos manipular la entrada que el programa espera por STDIN redirigiéndolo
desde cualquier fichero que queramos.


=head1 AUTHOR

Nicolás Pernas Maradei, E<lt>nicopernas@gmail.comE<gt>
Francisco José Cabrera Hernández, E<lt>alu3651@etsii.ull.esE<gt>
Romén Rodríguez Gil, E<lt>alu3718@etsii.ull.esE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2011 by Nicolás Pernas Maradei, Francisco José Cabrera Hernández, Romén Rodríguez Gil

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.9 or,
at your option, any later version of Perl 5 you may have available.


=cut
